<style>
  .container {
    width:100%;
    /*height: 100%;*/
    min-height: 800px;
    /*overflow:auto;*/
  }
  .nonworkday{
      background: #F0DFE5 !important;
  }
  .gantt_task_line, .gantt_line_wrapper {
    margin-top: -9px;
  }
  .gantt_side_content {
      margin-bottom: 7px;
  }
  .gantt_task_link .gantt_link_arrow {
      margin-top: -12px !important;
  }
  .gantt_side_content.gantt_right {
      bottom: 0;
  }
  .baseline {
    position: absolute;
    border-radius: 2px;
    opacity: 0.6;
    margin-top: -7px;
    height: 12px;
    background: #ffd180;
    border: 1px solid rgb(255,153,0);
  }
  .summary-row, .summary-row.odd {
    background-color: #EEEEEE !important;
    font-weight: bold;
  }
  .gantt_grid div, .gantt_data_area div {
    font-size: 12px;
  }
  .summary-bar {
    opacity: 0.4;
  }
  .gantt_task_cell.week_end {
    background-color: #EFF5FD;
  }
  .gantt_task_row.gantt_selected .gantt_task_cell.week_end {
    background-color: #F8EC9C;
  }
  .slack {
    position: absolute;
    border-radius: 0;
    opacity: 0.7;

    border: none;
    border-right: 1px solid #b6b6b6;
    margin-left: -2px;
    background: #b6b6b6;
    background: repeating-linear-gradient(
        45deg, #FFFFFF,
        #FFFFFF 5px,
        #b6b6b6 5px,
        #b6b6b6 10px
    );
  }
  .btn{
    font: 500 14px Roboto;
    border: 1px solid #D9D9D9;
    border-radius: 2px;
    background: #fff;
    padding: 4px 12px;
    margin: 0 5px;
    color: rgba(0,0,0,0.7);
    line-height: 20px;
    outline-color:#FFFAFA;
  }
  .complete_button{
    margin-top: 1px;
    /*background-image:url("public/components/starCloud/starComponents/gantt/project/v_complete.png");*/
    width: 20px;
  }
</style>
<template>
  <cliGenView>
    <div ref="ganttEl" class="container"></div>
    <project-toolbox slot="header" :gantt="gantt" :columns="completeColumns"></project-toolbox>
    <lightbox-modal :attrShow="attrShow" :editTask="editTask" :column="completeColumns" @updateAttrShow="attrShow=false" @handleSave="handleSave" @handleDelete="handleDelete" @handleCancel="handleCancel"></lightbox-modal>   
  </cliGenView>

</template>
<script>
  import gantt from 'public/3thComponents/gantt' ; // 引入模块
  import '../ganttExport.js';
  import 'public/3thComponents/gantt/codebase/dhtmlxgantt.css';
  import ProjectToolbox from "./parts/project-toolbox";
  import lightboxModal from './parts/lightboxModal';
  export default {
    name: 'starProject',
    components: {ProjectToolbox,lightboxModal},
    data() {
      let _this=this;
      return {
        completeLayout:{},
        completeColumns:[],
        completeConfig:{},
        groupbyOptions:[],
        defaultCfg:{

          sections:{
            reference:{name:"reference",label:"更多...",height:1,width:0,map_to:"task",type:"textarea",button:'reference'}, 
            task:{name:"task",label:"任务",height:30,map_to:"text",type:"textarea",focus:true}, 
            description:{name:"description",label:"描述",height:60,map_to:"desc",type:"textarea"},
            type:{name:"type",label:"任务类型",type:"typeselect",map_to:"type"},
            responsible:{name:"responsible",label:"负责人",type:"select",map_to:"holder"},
            workunit:{name:"workunit",label:"工位",type:"select",map_to:"workunit"}, 
            priority:{name:"priority",label:"优先级",height:22,map_to:"priority",type:"select", options:[
                {key:1,label:'High'},{key:2,label:'Normal'},{key:3,label:'Low'}]},
            split:{name:"split",label:'显示',type:"checkbox",map_to:"render",options:[{key:"split",label:"Split Task"}]},
            // constraint:{name:"constraint",label:"约束",type:"constraint"}, 
            actual:{name:"actual",label:"实际时间",height:25,map_to:"auto",type:"duration"},
            baseline:{name:"baseline",label:"计划时间",height:25,type:"duration",map_to:{start_date:"planned_start",end_date:"planned_end"}} 
          },
          sectionButtons:{
            save:{name:'gantt_save_btn',id:'icon_save',label:'保存',position:'left'},
            cancel:{name:'gantt_cancel_btn',id:'icon_cancel',label:'取消',position:'left'},
            complete:{name:'complete_button',id:'complete_button',label:'完成',position:'left'},
            delete:{name:'gantt_delete_btn',id:'icon_delete',label:'删除',position:'right'},
          },
        },
        gantt:null,
        ganttEl:null,
        // "minute", "hour", "day" (default), "week", "quarter", "month", "year"
        defaultTpl:{},
        //自定义lightbox的属性
        attrShow:false,
        editTask:null
      }
    },
    props:{
      columns:{
        default:()=>{
          return [];
        }
      },
      layoutType:{
        default:()=>{
          return ['default','split','complete'][1];
        }
      },
      isToolbar:{
        default:true
      },
      vm:{
        default:function(){
          return {};
        }
      },
      layout:{
        default:function(){
          return {
            type:'row',
            definedDef:false,//false:使用缺省定义；{...}:自定义
            additional:false,//false:不使用附加图；[]:使用缺省资源；[...]:自定义；
          }
        }
      },

      sections:{
        default:function(){
          return false;
        }
      },
      sectionButtons:{
        default:function(){
          return false;
        }
      },
      holiday:{
        default:function(){
          return [];
        }
      },
      scalesPattern:{
        default:function(){
          return [];
        }
      },
      scales:{
        default:function(){
          return [];
        }
      },
      config:{
        default:function(){
          return {}
        }
      },
      data:{
        default:function() {
          return {
            "tasks":[
              {"text":"New task #1","id":1650130202729,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-10-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202750,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202751,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202752,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202753,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202754,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #2","id":1650130202755,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #1","id":1650130202756,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #1","id":1650130202757,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fengjingshan","type":"task"},
              {"text":"New task #1","id":1650130202758,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #2","id":1650130202759,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #2","id":1650130202760,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #2","id":1650130202761,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #1","id":1650130202762,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #1","id":1650130202763,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #1","id":1650130202764,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #3","id":1650130202765,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"panhao","type":"task"},
              {"text":"New task #3","id":1650130202766,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202767,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202768,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202769,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202770,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202771,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"},
              {"text":"New task #3","id":1650130202772,"parent":0,"link":"","start_date":"2022-04-15 00:00","end_date":"2022-04-16 00:00","planned_start":"2022-04-17 00:00","planned_end":"2022-04-19 00:00","duration":1,"progress":0,"responsible":"fushubao","type":"task"}
            ],
            "link":[],
            "links":[]
          }
        }
      },
      tpl:{
        default:function(){
          return {};
        }
      },
    },
    provide: function () {
      return {
        toggleSlack: this.toggleSlack,
        updateCriticalPath: this.updateCriticalPath,
        groupBy: this.groupBy,
        getData: this.getData,
        submit: this.submit,
        refresh: this.refresh,
        exportExcel: this.exportExcel,
      }
    },
    mounted() {
      let _this=this;
      this.gantt=gantt;
      this.ganttEl=this.$refs._ganttEl;
      this.init();
      Object.assign(this.vm,{
        gantt:gantt,
        self:this
      });

      // this.gantt.resetLayout();
      this.$emit('update:vm',this.vm);
    },
    destroyed() {
      // this.gantt.destructor();
    },
    methods:{
      getDefault(){
        return this.definedDef;
      },
      initSections(){
        let sections=[];
        if(this.sections==false){
          sections=Object.values(this.defaultCfg.sections);
        }else{
          Object.keys(this.defaultCfg.sections).map(key=>{
            if(Object.keys(this.sections).includes(key)){
              if(this.sections[key]!==true&&this.sections[key]!==false){
                sections.push(Object.assign({},this.defaultCfg.sections[key],this.sections[key]));
              }
            }else{
              sections.push(Object.assign({},this.defaultCfg.sections[key]));
            }
          });
        };
        sections.map(item=>{
          if(Object.keys(item).includes('button')){
            gantt.locale.labels['button_'+item.button] = item.label;
            gantt.locale.labels['section_'+item.name] = item.label;
          }else{
            gantt.locale.labels['section_'+item.name] = item.label;
          }
        });
        let leftbuttons=[];
        let rightbuttons=[];
        if(this.sectionButtons===false){
          Object.values(this.defaultCfg.sectionButtons).map(item=>{
            if(item.position=='left'){
              leftbuttons.push(item.name);
            }else{
              rightbuttons.push(item.name);
            };
            gantt.locale.labels[item.id]=item.label;
          })
        };
        gantt.config.buttons_left=leftbuttons;
        gantt.config.buttons_right=rightbuttons;
        return sections;
      },
      initTpl(){
        let tpl={text:'',id:'',parent:'',link:'',start_date:'',end_date:'',planned_start:'',planned_end:'',duration:0,progress:0,holder:'',workunit:'',type:''};
        if(Object.keys(this.tpl).length>0){
          tpl=this.tpl;
        };
          tpl['id']='';
          tpl['parent']='';
          tpl['link']='';
          this.defaultTpl=tpl;
      },
      /*******************************************************************************
       * 初始化                                                                       *
       *******************************************************************************/
      init(){
        this.initLayout(this.layoutType);
        this.initColumns();
        this.handleConfig();
        this.initSections();
        this.initPlugin();
        this.initScales();
        this.initEvent();
        this.initPlanned();
        this.initGroup();
        this.initSlack();
        this.initTpl();
        //初始化自定义lightbox
        this.initCustomLightbox();
        this.gantt.init(this.$refs.ganttEl);
        this.gantt.parse(this.data);
      },
      /*******************************************************************************
       * 基本配置                                                                      *
       *******************************************************************************/
      handleConfig(){
        let config={
          /************************** 通常配置项 *****************************************/
          /** 布局配置 */
          layout : this.completeLayout,//布局配置
          readonly : false,//default:false,是否只读模式
          layer_attribute : "tasklayer",//defalut:data-layer,给task布局一个名称属性
          rtl : false,//defalut:false,布局是否从右到左
          /** 滚动条配置 */
          autoscroll : true,//default:true,自动显示滚动条
          autoscroll_speed : 50,//default:30,滚动条滚动速度
          scroll_size : 20,//defalut:undefined,滚动条高度/宽度
          scale_height : 35,//defalut:35,列头高度
          initial_scroll : false,//default:true,timeline内置滚动条时，是否显示最早的任务
          horizontal_scroll_key : "altKey",//设置控制键+鼠标滚轮控制水平滚动条，可能的配置包括："shiftKey"|"altKey"|"metaKey"|false
          preserve_scroll : true,//defalut:true,保留滚动条位置
          prevent_default_scroll : false,//defalut:false,是否屏蔽window的滚动条事件
          /** 自适应 */
          autofit : true,//default:false,grid列自动适应
          container_resize_method : "timeout",//default:'timeout'，自适应父容器尺寸
          container_resize_timeout : 300,//default:20,指定重新渲染时间间隔
          keep_grid_width : false,//default:false,改变列宽的时候，grid宽度是否改变
          /** 尺寸 */
          grid_width : 500,//default:360,grid宽度
          resize_rows : true,//defalut:false,是否可以改变行高
          row_height : 40,//defalut:35,table的行高
          min_task_grid_row_height : 30,//default:30，行高
          scale_offset_minimal : true,//defalut:true,最小刻度间隔
          scroll_on_click : true,//defalut:true,选中task，滚动条自动定位
          /** 操作 */
          keyboard_navigation : true,//default:true，开启按行键盘导航
          keyboard_navigation_cells : false,//default:false,按单元格导航
          /************************** grid配置 *****************************************/
          /** 列配置 */
          min_grid_column_width : 70,//default:70,最小列宽
          columns:this.completeColumns,
          grid_elastic_columns : true,//default:false,当grid尺寸发生变化的时候，column尺寸自动调整
          reorder_grid_columns:true,//default:false,拖拽改变列顺序
          /** 字段配置 */
          // root_id : 'root',//default:0,设置虚拟根id
          auto_types : true,//default:false,自动转换任务类型，如任务变成项目
          date_format : "%Y-%m-%d",//向后台保存的日期格式
          task_date : "%Y-%m-%d",
          date_grid : "%Y-%m-%d",//grid中显示的日期格式
          details_on_create : true,//default:true,add单击时，打开lightbox
          details_on_dblclick : true,//default:true,双击任务时，打开lightbox
          inline_editors_date_processing : "keepDates",//时间更新逻辑，可能的配置包括：undefined,"keepDuration","keepDates"
          min_duration : 24*60*60*1000,//default:60*60*1000, or 3600000 ms, 1 hour，最小任务时间
          constraint_types : {
            ASAP: "尽快",// As Soon As Possible，asap
            ALAP: "尽晚",// As Late As Possible,alap
            SNET: "开始不早于",// Start No Earlier Than,snet
            SNLT: "开始不晚于",// Start No Later Than,snlt
            FNET: "完成不早于",// Finish No Earlier Than,fnet
            FNLT: "完成不晚于",// Finish No Later Than,fnlt
            MSO: "必须开始",// Must Start On,mso
            MFO: "必须完成"// Must Finish On,mfo
          },
          /** grid操作 */
          cascade_delete : true,//default:true,级联删除
          multiselect : false,//default:true,是否可以多选
          multiselect_one_level : false,//default:false,是否只能在同级多选
          open_split_tasks : true,//是否可以收起父级
          open_tree_initially : false,//default:false,父级打开时，是否显示全部子项
          order_branch : true,//default:false,是否可以任务在相同级别排序
          order_branch_free : false,//default:false,是否可以任务全部排序
          placeholder_task : false,//default:false,是否开启新增行编辑
          redo : true,//default:true,开启redo,需要插件
          undo : true,//default:true,开启undo,需要插件
          /** 行编辑器 */
          editor_types:{custom_editor:{}},//自定义编辑器，预定义编辑器包括：text,number,date,select,predecessor
          /************************** timeline配置 *****************************************/
          /** 整体配置 */
          autosize : false,//default:false,强制timeline容纳所有task
          autosize_min_width : 800,//default:0,timeline最小宽度，小于该宽度则滚动条出现，取决于水平滚动条设置,autosize=true/'xy'/'y'时生效
          min_column_width : 70,//default:70,timeline最小列宽
          /** 图条配置 */
          bar_height : 16,//default:full,timeline图条高度
          round_dnd_dates : true,//default:true,s使能日期前后的圆环
          branch_loading : false,//default:false,动态加载图条
          xml_date : "%Y-%m-%d %H:%i:%s",//branch_loading=true时配置
          branch_loading_property : "hasChild",//default:$has_child,指定要加载的子任务，branch_loading=true时配置
          show_tasks_outside_timescale : true,//default:false,新增任务时，如果超出timeline，则自动适应
          /** 依赖线配置 */
          link_arrow_size : 6,//default:6,link的箭头尺寸
          link_attribute : "data-link-id",//default:data-link-id,给link一个属性名称
          link_line_width : 2,//default；2，link宽度
          link_wrapper_width : 20,//default:20,link的留白空间
          /** 图条拖动 */
          drag_links : true,//default:true,通过拖拽连接依赖
          drag_move : true,//default:true,task是否可以移动
          drag_multiple : false,//default:true,task是否可以多选移动
          drag_project : true,//default:true,project类型task是否可以拖拽
          drag_progress : true,//default:true,完成度是否可以拖拽
          drag_resize  : true,//default:true,任务时间是否可以拖拽
          fit_tasks  : true,//default:false,父级任务自动涵盖子任务
          highlight_critical_path : true,//default:false,路径高亮.需要插件支持
          /************************** calendar配置 *****************************************/
          calendar_property : "property_name",
          work_time : true,//计算工作日
          skip_off_time : false,//不显示工作日
          duration_unit : "day",//default;day,duration单位,可能的值"minute", "hour", "day","week", "month", "year"
          duration_step : 1,//时间步长
          correct_work_time : true,//default:false,拖拽时，纠正工作日
          dynamic_resource_calendars : true,//合并多个资源日历
          inherit_calendar : true,//default:false,是否继承全局日历
          inherit_scale_class : true,//default:false,是否继承父级刻度样式
          /************************** 数据配置 **********************************************/
          deepcopy_on_parse : false,//default:false，parse发生时复制数据，切断与源数据的联系
          /************************** lightbox配置 *****************************************/
          drag_lightbox : false,//default:true，lightbox是否可以拖拽
          /************************** 自动规划配置 *******************************************/
          auto_scheduling : true,
          auto_scheduling_compatibility : true,//default:false,强制时间
          auto_scheduling_descendant_links : true,//default:false,允许父项连接子项
          auto_scheduling_initial : false,//default:true,loading和parsing是否触发自动规划
          auto_scheduling_move_projects : true,//default:true,是否项目整体移动
          auto_scheduling_strict : true,//default:true,规划时，是否依照尽早日期
          schedule_from_end : false,//自动规划策略，向前规划和向后规划schedule_from_end=true为向后规划
          // project_end : new Date(2050, 2, 1),//向后规划：可以设定靠墙日期，开启as late as possible 模式
          // project_start : new Date(),//向前规划：可以设置尽早模式，as soon as possible 模式
          /************************** slack配置 *******************************************/
          show_slack:true,
        }
        this.completeConfig=config;
        this.gantt.config=Object.assign(this.gantt.config,config);
          /**
           * 其它
           */
          // this.gantt.config.editable_property = "property_name";
          // this.gantt.config.csp = "auto";
          /*this.gantt.config.click_drag={
            callback:(startPosition,endPosition,startDate,endDate,tasksBetween,rowsBetween)=>{

            },
            singleRow:true
          };*/
          // this.gantt.config.start_date = new Date(2018, 08, 10);
          // this.gantt.config.end_date = new Date(2018, 08, 20);
          // this.gantt.config.process_resource_assignments = false;

      },
      /**
       * 初始化布局
       */
      initLayout(type){
        //单行布局，分为两列，依次是grid、timeline
        let layout= {
          //同一的滚动条，grid部分保持不变，timeline滚动
          default:{
            css: "gantt_container",
            rows: [
              {
                cols: [
                  {view: "grid",id: "grid", scrollX: "scrollHor", scrollY: "scrollVer"},//grid
                  {resizer: true, width: 1},//可变尺寸的边框
                  {view: "timeline",id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},//时间线
                  {view: "scrollbar", id: "scrollVer"}//垂直滚动条
                ]
              },
              {view: "scrollbar", id: "scrollHor"}//水平滚动条
            ],
          },
          //grid和timeline分别有各自的水平滚动条，共用垂直滚动条
          split:{
            css: "gantt_container",
            cols: [
              {
                width:400,
                min_width: 300,
                rows:[
                  {view: "grid", id: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer"},
                  {view: "scrollbar", id: "gridScroll"}
                ]
              },
              {resizer: true, width: 1},
              {
                rows:[
                  {view: "timeline", id: "timeline", scrollX: "scrollHor", scrollable: true, scrollY: "scrollVer"},
                  {view: "scrollbar", id: "scrollHor"}
                ]
              },
              {view: "scrollbar", id: "scrollVer"}
            ]
          },
          //带有资源的布局
          complete: {
            css: "gantt_container",
            rows: [
              {
                cols: [
                  {view: "grid", id: "grid", group:"grids", scrollY: "scrollVer"},
                  {resizer: true, width: 1},
                  {view: "timeline", id: "timeline", scrollX: "scrollHor", scrollY: "scrollVer"},
                  {view: "scrollbar", id: "scrollVer", group:"vertical"}
                ],
                gravity:2
              },
              {resizer: true, width: 1},
              {
                // config: resourceConfig,
                cols: [
                  {view: "resourceGrid", id: "resourceGrid", group:"grids", bind:"resource",scrollY: "resourceVScroll" },
                  {resizer: true, width: 1},
                  {view: "resourceTimeline", id: "resourceTimeline",bind:"resource",bindLinks: null, scrollX: "scrollHor", scrollY: "resourceVScroll"},
                  {view: "scrollbar", id: "resourceVScroll", group:"vertical"}
                ],
                gravity:1
              },
              {view: "scrollbar", id: "scrollHor"}
            ]
          }
        }[type];
        this.completeLayout=layout;
        return layout;
      },
      initResourceLayout(){
        let resourceConfig = {
          scale_height: 30,
          scales: [
            {unit: "day", step: 1, date: "%d %M"}
          ],
          columns: [
            {
              name: "name", label: "Name", tree:true, width:250, template: function (resource) {
                return resource.text;
              }, resize: true
            },
            {
              name: "allocated", label: "Allocated", align:"left", width:100, template: function (resource) {
                var assignments = gantt.getResourceAssignments(resource.id);
                var result = 0;
                assignments.forEach(function(assignment){
                  var task = gantt.getTask(assignment.task_id);
                  if(resource.type == "work"){
                    result += task.duration * assignment.value;
                  }else{
                    result += assignment.value * 1;
                  }
                });

                if(resource.type == "work"){
                  result = "<b>" +result +  "</b> hours";
                }else{
                  result = "<b>" +result + "</b> " + resource.unit;
                }

                return result;
              }, resize: true
            }
          ]
        };
        let type=this.layout.type=='row'||this.layout.type=='col'?this.layout.type:'row';
        let layout=this.defaultCfg[type+'Layout'];
        if(this.layout.definedDef){
          Object.assign(layout,this.layout.definedDef);
        };
        if(this.layout.hasAdditional){
          if(type=='row'){
            if(this.layout.additional.length==0){
              this.defaultCfg.rowResource.config = resourceConfig;
              layout.rows=layout.rows.concat(this.defaultCfg.rowResource,this.defaultCfg.rowScroll);
            }else{
              layout.rows=layout.rows.concat(this.layout.additional,this.defaultCfg.rowScroll);
            }
          }
        }else{
          layout.rows=layout.rows.concat(this.defaultCfg.rowScroll);
        };
        return layout;

      },
      initResource(){
        gantt.$resourcesStore = gantt.createDatastore({
          name: 'resource',
          type: "treeDatastore",
          initItem: function (item) {
              item.parent = item.parent || gantt.config.root_id;
              item[gantt.config.resource_property] = item.parent;
              item.open = true;
              return item;
          }
        });
        gantt.$resourcesStore.attachEvent("onFilterItem", function(id, item) {
          return gantt.getResourceAssignments(id).length > 0;
        });
        gantt.init(this.$refs.ganttEl);

        gantt.$resourcesStore.attachEvent("onParse", function(){
          var people = [];
          gantt.$resourcesStore.eachItem(function(res){
              if(!gantt.$resourcesStore.hasChild(res.id)){
                  var copy = gantt.copy(res);
                  copy.key = res.id;
                  copy.label = res.text;
                  people.push(copy);
              }
          });
          gantt.updateCollection("people", people);
        });
        gantt.attachEvent("onParse", function(){
          gantt.render();
        });
        gantt.$resourcesStore.parse([
          {id: 1, text: "panhao", unit:"hours/day", default_value:8, type:"work"},
          {id: 2, text: "yangxiaopei", unit:"hours/day", default_value:8, type:"work"},
          {id: 3, text: "wangtao", unit:"hours/day", default_value:8, type:"work"},
        ]);
      },
      /**
       * 初始化gridColumns配置，合并外部与缺省值，保存在completeColumns
       * @returns {*|[{template: *, hide: boolean, selectable: boolean, name: string, width: number, resize: boolean, label: string, align: string}, {hide: boolean, selectable: boolean, name: string, tree: boolean, width: string, resize: boolean, label: string, align: string, "min-width": number}, {selectable: boolean, name: string, resize: boolean, label: string, "min-width": number}, {hide: boolean, selectable: boolean, name: string, width: number, resize: boolean, label: string, align: string}, {hide: boolean, selectable: boolean, name: string, width: number, resize: boolean, label: string, align: string}, null, null, null, null]}
       */
      initColumns(){
        let columns=[
          {name:"wbs",label:"序号",selectable:false,resize:true,hide:false,align:'left',width:40, template:gantt.getWBSCode},
          {name:"text",label:"任务名称",selectable:false,tree:true,resize:true,hide:false,align:'left',min_width:200,width:'*'},
          {name:"responsible",label:"负责人",grouped:true,selectable:true,resize:true,min_width:60, width: 80},
          // constraint_type:{name:"constraint_type",label:"约束",hide:true,resize:true,width:"*",align:"center"},
          // constraint_date:{name:"constraint_date",label:"约束时间",hide:true,resize:true,width:"*",align:"center"},
          {name:"planned_start",label:"计划开始时间",selectable:true,resize:true,hide:false,align:'center',width:80},
          {name:"planned_end",label:"计划结束时间",selectable:true,resize:true,hide:false,align:'center',width:80},
          {name:"start_date",label:"实际开始时间",grouped:true,selectable:true,resize:true,hide:false,align:'center',width:80},
          {name:"end_date",label:"实际结束时间",selectable:true,resize:true,hide:false,align:'center',width:80},
          {name:"duration",label:"期间",selectable:true,resize:true,hide:false,align:'center',width:30},
          {name:"progress",label:"进度",selectable:true,resize:true,hide:false,align:'center',width:40,template:item => {
            return (item.progress*100).toFixed(1)+'%';
          }},
        ];
        columns=columns.concat(this.columns);
        columns=this.lodash.uniqBy(columns,'name');
        if(!columns.find(item=>item.name==='add')){
          columns.push({name:"add",label:"",selectable:false,width:30})
        }
        this.completeColumns=columns;
        return columns;
      },
      /**
       * 初始化插件
       */
      initPlugin(){
        let plugins={};
        if(this.completeConfig.auto_scheduling){
          plugins['auto_scheduling']=true;
        };

        if(this.completeConfig.undo||this.completeConfig.redo){
          plugins['undo']=true;
        };
        if(this.completeConfig.highlight_critical_path){
          plugins['critical_path']=true;
        };
        if(this.completeConfig.group){
        };
        plugins['grouping']=true;
        if(this.completeConfig.marker){
        }
        plugins['marker']=true;
        this.gantt.plugins(plugins);
        let dateToStr = gantt.date.date_to_str(this.completeConfig.task_date);
        let todayMarker = this.gantt.addMarker({
          start_date: new Date(),
          css: "today",
          text:'今天',
          title:dateToStr( new Date())
        });
        // setInterval(function(){
        //   let today = this.gantt.getMarker(todayMarker);
        //   today.start_date = new Date();
        //   today.title = dateToStr(today.start_date);
        //   gantt.updateMarker(todayMarker);
        // }, 1000*60);
        // let start = new Date(2018, 2, 28);
        // gantt.addMarker({
        //   start_date: start,
        //   css: "status_line",
        //   text: "Start project",
        //   title: "Start project: " + dateToStr(start)
        // });
      },
      initScales(){
        let _this=this;
        let defaultScales={
          year:{unit: "year", step: 1, format: function (date) {return _this.formatter.year(date,"%YY")}},
          quarter:{unit: "quarter", step: 1, format: function(date){return "Q#"+_this.formatter.quarter(date,"%EQ")}},
          yearquarter:{unit: "quarter", step: 1, format: function (date) {return _this.formatter.year(date,"%YY")+" Q#"+_this.formatter.quarter(date,"%EQ")}},
          month:{unit: "month", step: 1, format: function (date) {return _this.formatter.month(date,"%EM")}},
          yearmonth:{unit: "month", step: 1, format: function (date) {return _this.formatter.year(date,"%YY")+"-"+_this.formatter.month(date,"%EM")}},
          yearquartermonth:{unit: "month", step: 1, format: function (date) {return _this.formatter.year(date,"%YY")+" Q#"+_this.formatter.quarter(date,"%EQ")+"-"+_this.formatter.month(date,"%EM")}},
          quartermonth:{unit: "month", step: 1, format: function (date) {return " Q#"+_this.formatter.quarter(date,"%EQ")+"-"+_this.formatter.month(date,"%EM")}},
          week:{unit: "week", step: 1, format: function (date) {return "Week #" + gantt.date.getWeek(date)}},
          workday:{unit: "day", step: 1, format: "%D", css: function(date){
            let dateToStr = gantt.date.date_to_str("%D");
            if (dateToStr(date) == "Sun"||dateToStr(date) == "Sat"){
              return "nonworkday";
            }else{
              return "";
            }
          }
          },
          day:{unit: "day", step: 1, format: function(date) {return _this.formatter.day(date,"%EN")}},
          date:{unit: "day", step: 1, format: function (date) {return _this.formatter.date(date,"%DD")}},
          daydate:{unit: "day", step: 1, format: function (date) {return _this.formatter.date(date,"%DD")+","+_this.formatter.day(date,"%EN")}},
          yearmonthdate:{unit: "day", step: 1, format: function (date) {return _this.formatter.year(date,"%YY")+"-"+_this.formatter.month(date,"%EM")+"-"+_this.formatter.date(date,"%DD")}},
          hour:{unit: "hour", step: 1, format: function(date) {return _this.formatter.hour(date,"%HH")}},
          minute:{unit: "minute", step: 1, format: function(date) {return _this.formatter.minute(date,"%MM")}},
        }
        let scalesPattern=["yearmonth","daydate"];
        let scales=[];
        if(this.scales.length>0){
          scales=this.scales;
        }else{
          if(this.scalesPattern.length!==0){
            scalesPattern=this.scalesPattern;
          };
          scalesPattern.forEach(function(item){
            if(defaultScales[item]){
              scales.push(defaultScales[item]);
            }
          });
          this.gantt.config.scale_height=this.scales.length*25<50?50:this.scales.length*25;
          this.gantt.config.scales=scales;
          if(this.completeConfig.work_time){
            if(this.holiday.length>0){
              this.holiday.map((date)=>{
                this.gantt.setWorkTime({date:new Date(date), hours:false})
              })
            }
          };
          this.gantt.templates.timeline_cell_class =(task, date) =>{
            if (!gantt.isWorkTime(date)) {
              return ("week_end");
            }
            return "";
          };

        }
      },
      initEvent(){
        let _this=this;
        this.gantt.form_blocks.textarea.button_click = function(index,button,shead,sbody){
          let id = gantt.getState().lightbox;
          let task=gantt.getTask(id);
          _this.$emit('reference',gantt,id,task,_this.data);
        };
        this.gantt.locale.labels["complete_button"] = "Complete";//配置按钮名称和显示标签
        this.gantt.attachEvent("onGanttReady", function(){//在甘特图加载完成后设置按钮
          // this.gantt.config.buttons_left = ["gantt_save_btn","gantt_cancel_btn","complete_button"];//左边按钮组
          // this.gantt.config.buttons_right = ["gantt_delete_btn","complete_button"];//右边按钮组
        });
        this.gantt.attachEvent("onLightboxButton", function(button_id, node, e){
          if(button_id == "complete_button"){
            let id = gantt.getState().lightbox;
            gantt.getTask(id).progress = 1;
            gantt.updateTask(id);
            gantt.hideLightbox();
          };

        });
        this.gantt.attachEvent("onAfterTaskAdd", function(id,item){
          _this.getData();
          _this.$emit('addTask',gantt,id,item,_this.data);
        });
        this.gantt.attachEvent("onAfterTaskUpdate", function(id,item){
          _this.getData();
          _this.$emit('updateTask',gantt,id,item,_this.data);
        });
        this.gantt.attachEvent("onAfterTaskDelete", function(id,item){
          _this.getData();
          _this.$emit('deleteTask',gantt,id,item,_this.data);
        });
        this.gantt.attachEvent("onAfterLinkAdd", function(id,item){
          _this.getData();
          _this.$emit('addLink',gantt,id,item,_this.data);
        });
        this.gantt.attachEvent("onAfterLinkDelete", function(id,item){
          _this.getData();
          _this.$emit('deleteLink',gantt,id,item,_this.data);
        });
        this.gantt.attachEvent("onAfterLinkUpdate", function(id,item){
          _this.getData();
          _this.$emit('updateLink',gantt,id,item,_this.data);
        });
      },
      initPlanned(){
        gantt.attachEvent("onTaskLoading", function(task){
          task.planned_start = gantt.date.parseDate(task.planned_start, "xml_date");
          task.planned_end = gantt.date.parseDate(task.planned_end, "xml_date");
          return true;
        });
        gantt.addTaskLayer({
          renderer: {
            render: function draw_planned(task) {
              if (task.planned_start && task.planned_end) {
                let sizes = gantt.getTaskPosition(task, task.planned_start, task.planned_end);
                let el = document.createElement('div');
                el.className = 'baseline';
                el.style.left = sizes.left + 'px';
                el.style.width = sizes.width + 'px';
                el.style.top = sizes.top + gantt.config.task_height + 13 + 'px';
                return el;
              }
              return false;
            },
            // define getRectangle in order to hook layer with the smart rendering
            getRectangle: function(task, view){
              if (task.planned_start && task.planned_end) {
                return gantt.getTaskPosition(task, task.planned_start, task.planned_end);
              }
              return null;
            }
          }
        });
        gantt.config.task_height=16;
        gantt.config.row_height=40;
      },
      initGroup(){
        this.gantt.templates.task_row_class = function (start, end, task) {
          if (task.$virtual)
            return "summary-row"
        };
        this.gantt.templates.task_class = function (start, end, task) {
          if (task.$virtual)
            return "summary-bar";
        };
      },
      initSlack(){/* show slack */
        let totalSlackColumn = {
          name: "totalSlack",
          align: "center",
          resize: true,
          width: 70,
          hide:true,
          label: "Total slack",
          template: (task)=> {
            if (this.gantt.isSummaryTask(task)) {
              return "";
            }
            return this.gantt.getTotalSlack(task);
          }
        }
        let freeSlackColumn = {
          name: "freeSlack",
          align: "center",
          resize: true,
          width: 70,
          hide:true,
          label: "Free slack",
          template: (task)=> {
            if (this.gantt.isSummaryTask(task)) {
              return "";
            }
            return this.gantt.getFreeSlack(task);
          }
        };
        this.gantt.config.columns = this.gantt.config.columns.concat([freeSlackColumn,totalSlackColumn]);

        this.gantt.config.show_slack = false;
        let _this=this;
        this.gantt.addTaskLayer(function addSlack(task) {
          if (!_this.gantt.config.show_slack) {
            return null;
          }
          let slack = _this.gantt.getFreeSlack(task);
          if (!slack) {
            return null;
          }
          let state = _this.gantt.getState().drag_mode;
          if (state == 'resize' || state == 'move') {
            return null;
          }
          let slackStart = new Date(task.end_date);
          let slackEnd = _this.gantt.calculateEndDate(slackStart, slack);
          let sizes = _this.gantt.getTaskPosition(task, slackStart, slackEnd);
          let el = document.createElement('div');
          el.className = 'slack';
          el.style.left = sizes.left + 'px';
          el.style.top = sizes.top + 2 + 'px';
          el.style.width = sizes.width + 'px';
          el.style.height = sizes.height + 'px';
          return el;
        });
      },
      /******************************************************************************
       * 工具方法
       ******************************************************************************/
      toggleSlack(e) {
        if (e.currentTarget.value=="显示裕度") {
          e.currentTarget.value = "隐藏裕度";
          //declaring custom config
          this.gantt.config.show_slack = true;
        } else {
          e.currentTarget.value = "显示裕度";
          this.gantt.config.show_slack = false;
        }
        this.gantt.render();
      },
      updateCriticalPath(e) {
        if (e.currentTarget.value=="显示关键路径") {
          e.currentTarget.value = "隐藏关键路径";
          gantt.config.highlight_critical_path = true;
        } else {
          e.currentTarget.value = "显示关键路径";
          gantt.config.highlight_critical_path = false;
        }
        gantt.render();
      },
      groupBy(v){
        if(v=='false'){
          gantt.groupBy(false);
          return;
        };
        let groupMap={};
        this.data.tasks.map(item=>{
          groupMap[item[v]]={label:item[v],key:item[v]}
        })
        gantt.groupBy({
          relation_property:v,
          groups:Object.values(groupMap),
          group_id:"key",
          group_text:"label"
        });
      },
      getData(){
        // this.$nextTick(()=>{
        let tasks=gantt.getTaskByTime();
        let links=gantt.getLinks();
        let newtasks=[];
        let newlinks=[];
        if(tasks.length>0){
          tasks.map(item=>{
            newtasks.push(this.tools.setObjectValues(this.tools.lodash.clone(this.defaultTpl),item));
          });
        };
        let dateToStr = gantt.date.date_to_str("%Y-%m-%d %H:%i");
        let formattasks=[];
        newtasks.map(item=>{
          Object.keys(item).map(key=>{
            if(['start_date','end_date','planned_start','planned_end'].includes(key)){
              // 解决新增任务时间不选时报错date.getFullYear is not a function
              if(!item[key])return;
              item[key]=dateToStr(item[key]);
            }
          })
          formattasks.push(item);
        })
        if(links.length>0){
          links.map((item,index)=>{
            newlinks.push(Object.assign({},item,{id:index+1}))
          })
        }
        this.$set(this.data,'tasks',formattasks);
        this.$set(this.data,'links',newlinks);

        // })
      },
      submit(e){
        this.getData();
        this.$emit('submit',gantt,this.data);
        console.log(JSON.stringify(this.data))
      },
      refresh(){
        gantt.render();
      },
      exportExcel(){
        let col = this.tools.lodash.clone(gantt._serialize_columns());
        gantt.config.columns.forEach(c => {
          if(c.hide === true){
            let i = col.findIndex(f => c.name === f.id);
            if(i>-1){
              col.splice(i,1);
            }
          }
        })
        col.forEach(c =>{
          if(c.id === "planned_start" || c.id === "planned_end"){
            c.type = 'date';
          }
        })
        let exCol = col.filter(c => c.id !== '_11' && c.id !== "_12");
        gantt.exportToExcel({
          columns:exCol,
          date_format:'yyyy-mm-dd hh:mm:ss'
        });
      },
      //初始化自定义lightbox
      initCustomLightbox(){
        var _this = this;
        gantt.showLightbox =  function (id){
          var task = gantt.getTask(id);
          _this.attrShow = true;
          _this.editTask = task;
        }
        gantt.hideLightbox = function () {
          _this.attrShow = false;
        };
      },
      //自定义lightbox增改
      handleSave(oldTask){
        let task = this.lodash.cloneDeep(oldTask)
        if (task.$new) {
          delete task.$new;
          gantt.addTask(task, task.parent);
        } else {
          gantt.updateTask(task.id,task);
        }
        gantt.hideLightbox();
      },
      //自定义lightbox删
      handleDelete(taskId){
        gantt.deleteTask(taskId);
        gantt.hideLightbox();
      },
      //自定义lightbox取消操作
      handleCancel(task){
        if (task.$new) gantt.deleteTask(task.id);
        gantt.hideLightbox();
      }

    }
  }
</script>